Hvordan kan det være at visse tilfeldige strenger produserer farger når de angis som bakgrunnsfarger i HTML? For eksempel: test ... produserer et dokument med rød bakgrunn på tvers av alle nettlesere og plattformer. Interessant, mens chucknorri også produserer en rød bakgrunn, produserer chucknorr en gul bakgrunn. Hva foregår her?
2020-12-07 21:57:15
Det er en holdover fra Netscape-dagene: Manglende sifre behandles som 0 [...]. Et feil siffer tolkes ganske enkelt som 0. For eksempel er verdiene # F0F0F0, F0F0F0, F0F0F, #FxFxFx og FxFxFx de samme. Det er fra blogginnlegget Litt rant om Microsoft Internet Explorer fargeanalyse som dekker det i detalj, inkludert varierende lengder på fargeværdier osv. Hvis vi bruker reglene etter tur fra blogginnlegget, får vi følgende: Erstatt alle ugyldige heksadesimale tegn med 0: chucknorris blir c00c0000000 Legg ut til neste totale antall tegn som kan deles med 3 (11 → 12): c00c 0000 0000 Del opp i tre like grupper, hvor hver komponent representerer den tilsvarende fargekomponenten i en RGB-farge: RGB (c00c, 0000, 0000) Trunker hvert av argumentene fra høyre ned til to tegn. Som til slutt gir følgende resultat: RGB (c0, 00, 00) = # C00000 eller RGB (192, 0, 0) Her er et eksempel som viser bgcolor-attributtet i aksjon for å produsere denne "fantastiske" fargeprøven:chuck norris Mr T ninjaturtle Dette svarer også på den andre delen av spørsmålet: Hvorfor produserer bgcolor = "chucknorr" en gul farge? Vel, hvis vi bruker reglene, er strengen: c00c00000 => c00 c00 000 => c0 c0 00 [RGB (192, 192, 0)] Noe som gir en lysegult gullfarge. Ettersom strengen starter med 9 tegn, beholder vi den andre ‘C’ denne gangen, og den ender derfor i den endelige fargeværdien. Jeg opplevde opprinnelig dette da noen påpekte at du kunne gjøre color = "crap", og vel, det blir brunt. | Jeg beklager å være uenig, men ifølge reglene for å analysere en eldre fargeverdi lagt ut av @Yuhong Bao, tilsvarer ikke chucknorris # CC0000, men heller # C00000, en veldig lik men litt annen fargetone av rødt. Jeg brukte Firefox ColorZilla-tillegget for å bekrefte dette. Reglene sier: gjør strengen til en lengde som er et multiplum av 3 ved å legge til 0s: chucknorris0 skille strengen i 3 like lange strenger: chuc knor ris0 avkort hver streng til 2 tegn: ch kn ri hold sekskantverdiene, og legg til 0-er der det er nødvendig: C0 00 00 Jeg var i stand til å bruke disse reglene for å tolke følgende strenger riktig: Lykkeamuletter Flaks LuckBeALady LuckBeALadyTonight GangnamStyle OPPDATERING: De opprinnelige svarerne som sa fargen var # CC0000 har siden redigert svarene for å inkludere rettelsen. | De fleste nettlesere vil rett og slett ignorere NON-hex verdier i fargestrengen din, og erstatte sifre uten hex med nuller. ChuCknorris oversettes til c00c0000000. På dette punktet vil nettleseren dele strengen i tre like deler, noe som indikerer røde, grønne og blå verdier: c00c 0000 0000. Ekstra biter i hver seksjon vil bli ignorert, noe som gjør det endelige resultatet # c00000 som er en rødaktig farge. Merk, dette gjelder ikke CSS-fargeanalyse, som følger CSS-standarden. syk dritt grass Rødaktig
Samme som ovenfor
Svart
| Årsaken er at nettleseren ikke kan forstå det og prøve å oversette det til det den kan forstå, og i dette tilfellet til en heksadesimal verdi! ... chucknorris starter med c som er gjenkjent tegn i heksadesimal, og det konverterer også alle ukjente tegn til 0! Så chucknorris i heksadesimalt format blir: c00c00000000, alle andre tegn blir 0 og c forblir der de er ... Nå blir de delt med 3 for RGB (rød, grønn, blå) ... R: c00c, G: 0000, B: 0000 ... Men vi vet at gyldig heksadesimal for RGB bare er 2 tegn, betyr R: c0, G: 00, B: 00 Så det virkelige resultatet er: bgcolor = "# c00000"; Jeg la også til trinnene i bildet som en rask referanse for deg: | Nettleseren prøver å konvertere chucknorris til hex-fargekode, fordi det ikke er en gyldig verdi. I chucknorris er ikke alt unntatt c en gyldig hex-verdi. Så det blir konvertert til c00c00000000. Som blir # c00000, en nyanse av rødt. Dette ser ut til å være et problem først og fremst med Internet Explorer og Opera (12), da både Chrome (31) og Firefox (26) bare ignorerer dette. P.S. Tallene i parentes er nettleserversjonene jeg testet på. På en lettere tone Chuck Norris overholder ikke nettstandardene. Nettstandarder samsvarer til ham. # BADA55 | WHATWG HTML-spesifikasjonen har den nøyaktige algoritmen for å analysere en eldre fargeverdi: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value. Koden Netscape Classic som brukes til å analysere fargestrenger er åpen kildekode: https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155. Legg for eksempel merke til at hvert tegn blir analysert som et heksesifret og deretter flyttes til et 32-biters heltall uten å sjekke om det er overløp. Bare åtte heksesifre passer inn i et 32-biters heltall, og det er derfor bare de siste 8 tegnene blir vurdert. Etter å ha parset heksesifrene i 32-biters heltall, blir de deretter avkortet til 8-biters heltall ved å dele dem med 16 til de passer inn i 8-bits, og derfor blir ledende nuller ignorert. Oppdatering: Denne koden samsvarer ikke akkurat med det som er definert i spesifikasjonen, men den eneste forskjellen det er noen få linjer med kode. Jeg tror det er disse linjene som ble lagt til (i Netscape 4): hvis (bytes_per_val> 4) { bytes_per_val = 4; } | Svar: Nettleseren vil prøve å konvertere chucknorris til en heksadesimal verdi. Siden c er det eneste gyldige hex-tegnet i chucknorris, blir verdien til: c00c00000000 (0 for alle verdiene som var ugyldige). Nettleseren deler deretter resultatet i 3 grupperinger: Rød = c00c, Grønn = 0000, Blå = 0000. Siden gyldige sekskantverdier for html-bakgrunner bare inneholder to sifre for hver fargetype (r, g, b), blir de to siste sifrene avkortet fra hver gruppe, og etterlater en rgb-verdi på c00000, som er en mursteinrød tonet farge. | chucknorris starter med c, og nettleseren leser den inn i en heksadesimal verdi. Fordi A, B, C, D, E og F er tegn i heksadesimal. Nettleseren konverterer chucknorris til en heksadesimal verdi, C00C00000000. Deretter konverteres den heksadesimale verdien C00C00000000 til RGB-format (delt på 3): C00C00000000 ⇒ R: C00C, G: 0000, B: 0000 Nettleseren trenger bare to sifre for å indikere fargen: R: C00C, G: 0000, B: 0000 ⇒ R: C0, G: 00, B: 00 ⇒ C00000 Vis til slutt bgcolor = C00000 i nettleseren. Her er et eksempel som viser det:| Reglene for å analysere farger på eldre attributter innebærer flere trinn enn de som er nevnt i eksisterende svar. Den avkortede komponenten til to sifre er beskrevet som: Kast alle tegn unntatt de siste 8 Kast ledende nuller en etter en så lenge alle komponentene har et ledende null Kast alle tegn unntatt de første 2 Noen eksempler: oooFoooFoooF 000F 000F 000F <- bytt ut, pute og del 0F 0F 0F <- ledende nuller avkortet 0F 0F 0F <- avkortet til 2 tegn fra høyre oooFooFFoFFF 000F 00FF 0FFF <- bytt ut, puten og klumpen 00F 0FF FFF <- ledende nuller avkortet 00 0F FF <- avkortet til 2 tegn fra høyre ABCooooooABCooooooABCoooooo ABC000000 ABC000000 ABC000000 <- bytt ut, put og del BC000000 BC000000 BC000000 <- avkortet til 8 tegn fra venstre BC BC BC <- avkortet til 2 tegn fra høyre AoCooooooAoCooooooAoCoooooo A0C000000 A0C000000 A0C000000 <- bytt ut, pute og del 0C000000 0C000000 0C000000 <- avkortet til 8 tegn fra venstre C000000 C000000 C000000 <- ledende nuller avkortet C0 C0 C0 <- avkortet til 2 tegn fra høyre Nedenfor er en delvis implementering av algoritmen. Den håndterer ikke feil eller tilfeller der brukeren angir en gyldig farge. funksjon parseColor (input) { // todo: return error if input is "" input = input.trim (); // todo: return error if input is "transparent" // todo: returner tilsvarende #rrggbb hvis input er en navngitt farge // todo: return #rrggbb if input matches #rgb // todo: erstatt unicode-kodepunkter som er større enn U + FFFF med 00 hvis (input.length> 128) { input = input.skive (0, 128); } if (input.charAt (0) === "#") { input = input.skive (1); } input = input.replace (/ [^ 0-9A-Fa-f] / g, "0"); mens (input.length === 0 || input.length% 3> 0) { input + = "0"; } var r = input.slice (0, input.length / 3); var g = input.skive (input.length / 3, input.length * 2/3); var b = input.skive (input.length * 2/3); hvis (r. lengde> 8) { r = r. skive (-8); g = g. skive (-8); b = b.skive (-8); } mens (r.length> 2 && r.charAt (0) === "0" && g.charAt (0) === "0" && b.charAt (0) === "0") { r = r. skive (1); g = g. skive (1); b = b. skive (1); } hvis (r. lengde> 2) { r = r. skive (0, 2); g = g. skive (0, 2); b = b. skive (0, 2); } returner "#" + r.padStart (2, "0") + g.padStart (2, "0") + b.padStart (2, "0"); } $ (funksjon () { $ ("# input"). on ("endre", funksjon () { var input = $ (dette) .val (); var color = parseColor (input); var $ celler = $ ("# resultat tbody td"); $ cells.eq (0) .attr ("bgcolor", input); $ cells.eq (1) .attr ("bgcolor", farge); varverdi: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value. Koden Netscape Classic som brukes til å analysere fargestrenger er åpen kildekode: https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155. Legg for eksempel merke til at hvert tegn blir analysert som et heksesifret og deretter flyttes til et 32-biters heltall uten å sjekke om det er overløp. Bare åtte heksesifre passer inn i et 32-biters heltall, og det er derfor bare de siste 8 tegnene blir vurdert. Etter å ha parset heksesifrene i 32-biters heltall, blir de deretter avkortet til 8-biters heltall ved å dele dem med 16 til de passer inn i 8-bits, og derfor blir ledende nuller ignorert. Oppdatering: Denne koden samsvarer ikke akkurat med det som er definert i spesifikasjonen, men den eneste forskjellen det er noen få linjer med kode. Jeg tror det er disse linjene som ble lagt til (i Netscape 4): hvis (bytes_per_val> 4) { bytes_per_val = 4; } | Svar: Nettleseren vil prøve å konvertere chucknorris til en heksadesimal verdi. Siden c er det eneste gyldige hex-tegnet i chucknorris, blir verdien til: c00c00000000 (0 for alle verdiene som var ugyldige). Nettleseren deler deretter resultatet i 3 grupperinger: Rød = c00c, Grønn = 0000, Blå = 0000. Siden gyldige sekskantverdier for html-bakgrunner bare inneholder to sifre for hver fargetype (r, g, b), blir de to siste sifrene avkortet fra hver gruppe, og etterlater en rgb-verdi på c00000, som er en mursteinrød tonet farge. | chucknorris starter med c, og nettleseren leser den inn i en heksadesimal verdi. Fordi A, B, C, D, E og F er tegn i heksadesimal. Nettleseren konverterer chucknorris til en heksadesimal verdi, C00C00000000. Deretter konverteres den heksadesimale verdien C00C00000000 til RGB-format (delt på 3): C00C00000000 ⇒ R: C00C, G: 0000, B: 0000 Nettleseren trenger bare to sifre for å indikere fargen: R: C00C, G: 0000, B: 0000 ⇒ R: C0, G: 00, B: 00 ⇒ C00000 Vis til slutt bgcolor = C00000 i nettleseren. Her er et eksempel som viser det: chucknorris c00c00000000 c00000 | Reglene for å analysere farger på eldre attributter innebærer flere trinn enn de som er nevnt i eksisterende svar. Den avkortede komponenten til to sifre er beskrevet som: Kast alle tegn unntatt de siste 8 Kast ledende nuller en etter en så lenge alle komponentene har et ledende null Kast alle tegn unntatt de første 2 Noen eksempler: oooFoooFoooF 000F 000F 000F <- bytt ut, pute og del 0F 0F 0F <- ledende nuller avkortet 0F 0F 0F <- avkortet til 2 tegn fra høyre oooFooFFoFFF 000F 00FF 0FFF <- bytt ut, puten og klumpen 00F 0FF FFF <- ledende nuller avkortet 00 0F FF <- avkortet til 2 tegn fra høyre ABCooooooABCooooooABCoooooo ABC000000 ABC000000 ABC000000 <- bytt ut, put og del BC000000 BC000000 BC000000 <- avkortet til 8 tegn fra venstre BC BC BC <- avkortet til 2 tegn fra høyre AoCooooooAoCooooooAoCoooooo A0C000000 A0C000000 A0C000000 <- bytt ut, pute og del 0C000000 0C000000 0C000000 <- avkortet til 8 tegn fra venstre C000000 C000000 C000000 <- ledende nuller avkortet C0 C0 C0 <- avkortet til 2 tegn fra høyre Nedenfor er en delvis implementering av algoritmen. Den håndterer ikke feil eller tilfeller der brukeren angir en gyldig farge. funksjon parseColor (input) { // todo: return error if input is "" input = input.trim (); // todo: return error if input is "transparent" // todo: returner tilsvarende #rrggbb hvis input er en navngitt farge // todo: return #rrggbb if input matches #rgb // todo: erstatt unicode-kodepunkter som er større enn U + FFFF med 00 hvis (input.length> 128) { input = input.skive (0, 128); } if (input.charAt (0) === "#") { input = input.skive (1); } input = input.replace (/ [^ 0-9A-Fa-f] / g, "0"); mens (input.length === 0 || input.length% 3> 0) { input + = "0"; } var r = input.slice (0, input.length / 3); var g = input.skive (input.length / 3, input.length * 2/3); var b = input.skive (input.length * 2/3); hvis (r. lengde> 8) { r = r. skive (-8); g = g. skive (-8); b = b.skive (-8); } mens (r.length> 2 && r.charAt (0) === "0" && g.charAt (0) === "0" && b.charAt (0) === "0") { r = r. skive (1); g = g. skive (1); b = b. skive (1); } hvis (r. lengde> 2) { r = r. skive (0, 2); g = g. skive (0, 2); b = b. skive (0, 2); } returner "#" + r.padStart (2, "0") + g.padStart (2, "0") + b.padStart (2, "0"); } $ (funksjon () { $ ("# input"). on ("endre", funksjon () { var input = $ (dette) .val (); var color = parseColor (input); var $ celler = $ ("# resultat tbody td"); $ cells.eq (0) .attr ("bgcolor", input); $ cells.eq (1) .attr ("bgcolor", farge); var chucknorris c00c00000000 c00000